package com.gylang.easy.lazy;

import cn.hutool.core.collection.CollUtil;
import com.gylang.easy.util.Asserts;
import lombok.*;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * @author gylang
 * data 2021/7/20
 */
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class Recursion<T> {

	private Consumer<T> consumer;

	private T bean;
	private Iterable<T> list;

	public Function<T, Iterable<T>> iterableFunc;


	public void top2Bottom() {

		Asserts.notNull(consumer, "消费者不能为空");
		Asserts.notNull(bean, "递归对象不能为空");
		Asserts.notNull(iterableFunc, "递归对象策略方法不能为空");
		top2Bottom(bean);
	}

	private void top2Bottom(T t) {

		Asserts.notNull(consumer, "消费者不能为空");
		Asserts.notNull(bean, "递归对象不能为空");
		Asserts.notNull(iterableFunc, "递归对象策略方法不能为空");
		consumer.accept(t);
		Iterable<T> iterable = iterableFunc.apply(t);
		if (CollUtil.isNotEmpty(iterable)) {
			for (T child : iterable) {
				top2Bottom(child);
			}
		}
	}

	public void listTop2Bottom() {

		Asserts.notNull(consumer, "消费者不能为空");
		Asserts.notNull(list, "递归对象不能为空");
		Asserts.notNull(iterableFunc, "递归对象策略方法不能为空");
		listTop2Bottom(list);
	}

	private void listTop2Bottom(Iterable<T> list) {

		Asserts.notNull(consumer, "消费者不能为空");
		Asserts.notNull(bean, "递归对象不能为空");
		Asserts.notNull(iterableFunc, "递归对象策略方法不能为空");
		for (T t : list) {
			consumer.accept(t);
		}
		for (T t : list) {
			Iterable<T> iterable = iterableFunc.apply(t);
			if (CollUtil.isNotEmpty(iterable)) {
				for (T child : iterable) {
					top2Bottom(child);
				}
			}
		}

	}


}
